﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections;
using System.Threading;

using com.ubosi.spider.core.Net;
using com.ubosi.spider.config;

namespace com.ubosi.spider.app
{

    /// <summary>
    /// 代理服务器包装类,具有引用计数生存期管理等功能
    /// </summary>
    internal class WebProxyAgent
    {        
        private WebProxy _proxy;
        private int _refCount = 0;
        public string Key
        {
            get
            {
                return _proxy.Address.AbsoluteUri;
            }
        }
        public WebProxyAgent(WebProxy proxy)
        {
            this._proxy = proxy;
            this._refCount = 0;            
        }
        public void AddRef()
        {
            
        }
        public WebProxy GetProxy()
        {            
            return _proxy;        
        }
        public void Reset()
        {            
            _refCount = 0;
        }
        public void Release()
        {           
        }
    }
    /// <summary>
    /// 代理服务器容器，用来管理代理服务器的使用
    /// </summary>
    public class SpiderWebProxyContainer : IWebProxyContainer
    {               
        private List<WebProxyAgent> _proxyAgents;
              
        public SpiderWebProxyContainer()
        {
            _proxyAgents = new List<WebProxyAgent>();                                   
           
        }
        public void Add(IWebProxy proxy)
        {
            WebProxy webProxy = proxy as WebProxy;
            if (webProxy == null)
            {                
                return;
            }
            WebProxyAgent proxyAgent = new WebProxyAgent(webProxy);
                          
                _proxyAgents.Add(proxyAgent);
            
        }

        public void Remove(IWebProxy proxy)
        {
            WebProxy webProxy = proxy as WebProxy;
            if (webProxy == null)
                return;
            string key = webProxy.Address.AbsoluteUri;
           
            //using(ReaderWriterLockObject readObject = _lockHelper.CreateAcquireReaderLocker())
            {
                WebProxyAgent proxyAgent = null;
                for (int i = 0; i < _proxyAgents.Count; i++)
                {
                    if (string.Compare(_proxyAgents[i].Key, key, true) == 0)
                    {
                        proxyAgent = _proxyAgents[i];
                        break;
                    }
                }
                if (proxyAgent != null)
                {//增加引用计数，相当于禁用了该代理
                    proxyAgent.AddRef();
                }
            }
        }

        public IWebProxy GetProxy()
        {           
            WebProxy proxy = null;             
            //using (ReaderWriterLockObject readObject = _lockHelper.CreateAcquireReaderLocker())
            {
                if (_proxyAgents.Count == 0)
                    return null;
                for (int i = 0; i < _proxyAgents.Count; i++)
                {
                    WebProxyAgent proxyAgent = _proxyAgents[i];
                    proxy = proxyAgent.GetProxy();
                    if (proxy != null)
                        break;
                }
            }                
            if (proxy == null)
            {
                //TraceWarning("无可用代理，尝试重新启用所有已禁用的代理...");
                //using (ReaderWriterLockObject readObject = _lockHelper.CreateAcquireReaderLocker())
                {
                    for (int i = 0; i < _proxyAgents.Count; i++)
                    {
                        _proxyAgents[i].Reset();
                    }
                    proxy = _proxyAgents[0].GetProxy();
                }               
            }
          
            return proxy;
        }

        public void Release(IWebProxy proxy)
        {
            WebProxy webProxy = proxy as WebProxy;
            if (webProxy == null)
                return;
            string key = webProxy.Address.AbsoluteUri;
            //using (ReaderWriterLockObject readObject = _lockHelper.CreateAcquireReaderLocker())
            {
                WebProxyAgent proxyAgent = null;
                for (int i = 0; i < _proxyAgents.Count; i++)
                {
                    if (string.Compare(_proxyAgents[i].Key, key, true) == 0)
                    {
                        proxyAgent = _proxyAgents[i];
                        break;
                    }
                }
                if (proxyAgent != null)
                    proxyAgent.Release();
            }
        }

        public void NotifyError(IWebProxy proxy, Exception ex)
        {
            WebProxy webProxy = proxy as WebProxy;
            if (webProxy == null)
                return;
            WebException webEx = ex as WebException;
            if (webEx != null)
            {
              
                HttpWebResponse response = webEx.Response as HttpWebResponse;
                if( response != null )
                {
                    //找不到页面的错误不删除代理
                    if (response.StatusCode == HttpStatusCode.NotFound)
                        return;
                } 

            }
            this.Remove(proxy);

        }        
    }

}
